package com.zyao89.view.zloading.star;

import com.zyao89.view.zloading.ZLoadingBuilder;
import com.zyao89.view.zloading.util.NumCalcUtil;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.ColorFilter;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.app.Context;

/**
 * Created by zyao89 on 2017/3/20.
 * Contact me at 305161066@qq.com or zyao89@gmail.com
 * For more projects: https://github.com/zyao89
 * My Blog: http://zyao89.me
 */
public class LeafBuilder extends ZLoadingBuilder {

    // 最终阶段
    private static final int FINAL_STATE = 2;
    private Paint mFullPaint;

    // 属性
    private float mStarOutR;
    private float mStarInR;
    private float mStarOutMidR;
    private float mStarInMidR;
    private float mCenterCircleR;
    private int mRotateAngle;

    // 当前动画阶段
    private int mCurrAnimatorState = 0;
    private Path mStarPath;

    @Override
    protected void initParams(Context context, Color color) {
        initPaint(color);

        // 最外层半径
        mStarOutR = getAllSize();

        // 外层贝塞尔曲线中间值
        mStarOutMidR = mStarOutR * 0.9f;

        // 内层半径
        mStarInR = mStarOutR * 0.7f;

        // 内层贝塞尔曲线中间值
        mStarInMidR = mStarOutR * 0.3f;

        // 中心圆半径
        mCenterCircleR = dip2px(context, 3);

        // 旋转角度
        mRotateAngle = 0;

        // 路径
        mStarPath = new Path();
    }

    /**
     * 初始化画笔
     *
     * @param color 画笔颜色
     */
    private void initPaint(Color color) {
        mFullPaint = new Paint();
        mFullPaint.setStyle(Paint.Style.FILL_STYLE);
        mFullPaint.setStrokeWidth(2);
        mFullPaint.setColor(color);
        mFullPaint.setDither(true);
        mFullPaint.setFilterBitmap(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.save();

        // 旋转
        canvas.rotate(mRotateAngle, getViewCenterX(), getViewCenterY());

        // 路径
        createStarPath(mStarPath, 5, -18);

        // 路径加入中心圆
        mStarPath.addCircle(getViewCenterX(), getViewCenterY(), mCenterCircleR, Path.Direction.CLOCK_WISE);

        // 这个很关键，选择路径填充方式
        mStarPath.setFillType(Path.FillType.EVEN_ODD);

        // 绘制
        canvas.drawPath(mStarPath, mFullPaint);
        canvas.restore();
    }

    /**
     * 绘制五叶草
     *
     * @param path 路径
     * @param num 角数量
     * @param startAngle 初始角度
     * @return
     */
    private void createStarPath(Path path, int num, int startAngle) {
        path.reset();
        int angle = 360 / num;
        int roundSize = 5; // 圆角弧度
        int offsetAngle = angle / 2;
        path.moveTo(NumCalcUtil.add(getViewCenterX(), mStarOutMidR * cos(startAngle - roundSize)),
                NumCalcUtil.add(getViewCenterY(), mStarOutMidR * sin(startAngle - roundSize)));
        for (int i = 0; i < num; i++) {
            int value = angle * i + startAngle;
            path.lineTo(NumCalcUtil.add(getViewCenterX(), mStarOutMidR * cos(value - roundSize)),
                    NumCalcUtil.add(getViewCenterY(), mStarOutMidR * sin(value - roundSize)));

            // 圆角
            path.quadTo(NumCalcUtil.add(getViewCenterX(), mStarOutR * cos(value)),
                    NumCalcUtil.add(getViewCenterY(), mStarOutR * sin(value)),
                    NumCalcUtil.add(getViewCenterX(), mStarOutMidR * cos(value + roundSize)),
                    NumCalcUtil.add(getViewCenterY(), mStarOutMidR * sin(value + roundSize)));
            path.lineTo(NumCalcUtil.add(getViewCenterX(), mStarInR * cos(value + offsetAngle - roundSize)),
                    NumCalcUtil.add(getViewCenterY(), mStarInR * sin(value + offsetAngle - roundSize)));

            // 内圆角
            path.quadTo(NumCalcUtil.add(getViewCenterX(), mStarInMidR * cos(value + offsetAngle)),
                    NumCalcUtil.add(getViewCenterY(), mStarInMidR * sin(value + offsetAngle)),
                    NumCalcUtil.add(getViewCenterX(), mStarInR * cos(value + offsetAngle + roundSize)),
                    NumCalcUtil.add(getViewCenterY(), mStarInR * sin(value + offsetAngle + roundSize)));
        }
        path.close();
    }

    @Override
    protected void setAlpha(int alpha) {
        mFullPaint.setAlpha(alpha);
    }

    @Override
    protected void prepareStart(AnimatorValue floatValueAnimator) {
        floatValueAnimator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
    }

    @Override
    protected void prepareEnd() {

    }

    @Override
    protected void computeUpdateValue(AnimatorValue animation, float animatedValue) {
        switch (mCurrAnimatorState) {
            case 0:
                mStarOutMidR = getAllSize() * animatedValue;
                mRotateAngle = (int) (360 * animatedValue);
                break;
            case 1:
                mRotateAngle = (int) (360 * NumCalcUtil.subtract(1, animatedValue));
                break;
            case 2:
                mStarOutMidR = getAllSize() * NumCalcUtil.subtract(1, animatedValue);
                break;
        }
    }

    @Override
    protected void setColorFilter(ColorFilter colorFilter) {
        mFullPaint.setColorFilter(colorFilter);
    }

    protected final float cos(int num) {
        return (float) Math.cos(num * Math.PI / 180);
    }

    protected final float sin(int num) {
        return (float) Math.sin(num * Math.PI / 180);
    }

    @Override
    public void onRepeat(Animator animator) {
        if (++mCurrAnimatorState > FINAL_STATE) {
            mCurrAnimatorState = 0;
        }
    }
}
